// Global Variables
var map
var lat, lon;
var geoAttempts = 0;

var showNearby = false
var mapRoutes = []
var mapVehicles = []
var stopMarkers = {}
var vehicleMarkers = {}
var vehicles = {}

// Stop colors available
var stopColors = ["b","g","p","r","y"]

// an infowindow that will be used to display pop-up info-windows
var infowindow = new google.maps.InfoWindow();

// Load the map when the map page has initialized
$("#page_map").live("pageinit", function() {
	geoLocation();
})

// Clicking on "me" will plot all nearby stops relative
// to the user's current location
$('.me').live("click", function() {
	if (map == null)
	{
		geoLocation();
		showNearby = true
	}
	addNearbyStops()
})

//refreshing vehicle markers
$(document).ready(function() {
	setInterval('refreshVehicles()', 3000);
})

function geoLocation() {

    if (navigator.geolocation) {  // try to get user's geoLocation
        navigator.geolocation.getCurrentPosition (function(position) {
          lat = position.coords.latitude;
          lon = position.coords.longitude;
        });
    }
    else {  // centre on UTSC
          lat = 43.78646;
          lon = -79.1884399;
    }
    
    /*  need user's geoLocation before drawing map, so block here
	until geoLocation is determined */
    if (geoAttempts < 10 && (lat==null || lon==null)) {  // keep trying until geoLocation determined
		geoAttempts += 1
		
		setTimeout(geoLocation, 500);
    }
    // Got location, let's draw the map
    else {
		createMap(lat, lon);
		drawMap(lat, lon);
	}
}

// Returns hover text given a nearby stop 
function makeNearbyHoverText(stopInfo)
{
	return stopInfo[0] + ', route: ' + stopInfo[4] + ', run: ' + stopInfo[5]
		+ ', distance: ' + stopInfo[6].toFixed(0) + 'm';
}

//return the color of bus
function getBusColour(direction)
{
	if (direction == "North" || direction == "West")
		return "media/redbus.png"
	else if (direction == "East" || direction == "South")
		return "media/bus.png"
	else
		return "media/greybus.png"
}

//choosing what to display on nearby stop click
function getNearbyRun(prediction)
{
	if (prediction.run_name != null)
		return prediction.run_name
	else
		return prediction.run_id
}

//set text for nearby stop marker popup
function makeNearbyClickText(stopInfo, marker)
{
	var stopID = stopInfo[3]
	if (stopID == "")
		return ""
	var text
	$.getJSON(rosseletURL + "getpredruns.php?id=" + stopID, function(data) {
		var predictItems = data.items
		text = "<p><b>" + stopInfo[0] + "</b></br>"
		text += "Next buses in...</p><ul>"
		$.each(predictItems, function(index, prediction) {
			if (prediction.minutes == 0)
				text += "<li>Now!</li> - " + getNearbyRun(prediction)
			else
				text += "<li>" + prediction.minutes + " minutes, " + (prediction.seconds - 60*prediction.minutes) + " seconds</li> - " + getNearbyRun(prediction)
		})
		text += "<ul>"
		infowindow.setContent(text);
		infowindow.open(map, marker);
	})
}

//set text for stop marker popup
function makeStopText(stopInfo, marker)
{
	var stopID = stopInfo[4]
	var text = ""
	
	if (stopID == "")
		return ""
	
	$.getJSON(rosseletURL + "getpredictions.php?id=" + stopID, function(data) {
		var predictItems = data.items
		if (stopInfo[5] == null)
			text = "<p><b>" + stopInfo[0] + " - " + stopInfo[1] + "</b>"
		else
			text = "<p><b>" + stopInfo[5] + " - " + stopInfo[1] + "</b>"
		text += "</br>Next buses in...</p><ul>"
		$.each(predictItems, function(index, prediction) {
			if (prediction.minutes == 0)
				text += "<li>Now!</li>"
			else
				text += "<li>" + prediction.minutes + " minutes</li>"
		})
		text += "<ul>"
		infowindow.setContent(text);
		infowindow.open(map, marker);
	})
}

//get stop predictions given the stop id
function getStopPredictions(stopID)
{
	$.getJSON(rosseletURL + "getpredictions.php?id=" + stopID, function(data) {
		var predictItems = data.items
		var text = "Next buses in...<ul>"
		$.each(predictItems, function(index, prediction) {
			text += "<li>" + prediction.minutes + " minutes</li>"
		})
		text += "<ul>"
	})
}

// Adding stop markers
function addNewStopMarkers(routeid)
{
	if(!stopMarkers[routeid]){
		stopMarkers[routeid] = []
		addRouteStops(routeid)
	}
}

//delete stop markers for a given route
function deleteStopMarkers(routeid)
{
	$.each(stopMarkers[routeid], function(index, marker)
	{
		if (marker)
			marker.setMap(null);
	})
	delete stopMarkers[routeid]
}

function addRouteStops(routeid)
{
	var locations = []
	$.getJSON(serviceURL + 'php/route_stops.php?routeids=' + routeid, function(data) {
		
		var stopList = data.items;  // extract the list of nearby stops
		$.each(stopList, function(index, stop) {
			locations.push([stop.runid, stop.display_name, stop.latitude, stop.longitude, stop.stopid, stop.direction_name])  // convert mile distance to meters				
		});
		
		addRouteMarkers(locations, routeid);
	})	
}

// add a map marker for each route stop
function addRouteMarkers(locations, routeid) {
	var text
	var marker
	console.log(Object.keys(stopMarkers))
	var colorId = Object.keys(stopMarkers).indexOf(routeid) % stopColors.length
	var baseName = "media/" + stopColors[colorId]
	var iconName
	
	for (var i = 0; i < locations.length; i++) {
		iconName = baseName
		if (locations[i][5] == null)
		{
			text = locations[i][0] + " - " + locations[i][1]
			iconName += ".png"
		}
		else {
			text = locations[i][5] + " - " + locations[i][1]
			switch(locations[i][5])
			{
				case "North":
					iconName += "north.png"
					break;
				case "West":
					iconName += "west.png"
					break;
				case "South":
					iconName += "south.png"
					break;
				case "East":
					iconName += "east.png"
					break;
				default:
					iconName += ".png"
					break;
			}
		}
		
		marker = new google.maps.Marker({
			position: new google.maps.LatLng(locations[i][2], locations[i][3]),
			map: map,
			title: text,
			icon: iconName
			
		});
		stopMarkers[routeid].push(marker);
		
		google.maps.event.addListener(marker, 'click', (function(marker, i) {
			return function() {
				makeStopText(locations[i], marker)
			}
		})(marker, i));
	}
}

// vehicle marker related

function addNewVehicleMarkers(routeid)
{
	if(!vehicleMarkers[routeid]){
		vehicleMarkers[routeid] = {}
		addRouteVehicles(routeid)
	}
}

// Delete all vehicle markers on the route
function deleteVehicleMarkers(routeid)
{

	$.each(vehicleMarkers[routeid], function(vehicleid, marker)
	{
		deleteSingleVehicle(routeid, vehicleid)
	})
	delete vehicleMarkers[routeid]
}

// Delete a vehicle marker from the map
function deleteSingleVehicle(routeid, vehicleid){
	vehicleMarkers[routeid][vehicleid].setMap(null);
	
	// no longer need to keep a reference to it
	delete vehicleMarkers[routeid][vehicleid];
}

// Get all vehicles on the route to the map
function addRouteVehicles(routeid)
{
	var locations = []
	
	$.getJSON(rosseletURL + 'getvehruns.php?id=' + routeid, function(data) {
		
		var vehicleList = data.items;  // extract the list of nearby stops
		$.each(vehicleList, function(index, vehicle) {
			locations.push([vehicle.latitude, vehicle.longitude, vehicle.dir_name, vehicle.id, vehicle.run_id, vehicle.run_name]) 
		});
		
		addVehicleMarkers(locations, routeid);
	})	
}

// Add markers for all vehicles on the route
function addVehicleMarkers(locations, routeid)
{
	for (var i = 0; i < locations.length; i++) {
		drawVehicleMarker(routeid, locations[i])
	}
}

// Draw a vehicle marker on the map
function drawVehicleMarker(routeid, location)
{
	// Get direction name if available, else get run ID
	if (location[2] == null)
		direction = location[4]
	else
		direction = location[2]
		
	// Build mouseover text
	if (location[5] == null)
		vehText = location[4] + " - " + location[3]
	else
		vehText = location[5] + " - " + location[3]
	
	// Get bus colour
	busColour = getBusColour(direction)
	// Add marker
	marker = new google.maps.Marker({
		position: new google.maps.LatLng(location[0], location[1]),
		map: map,
		icon: busColour,
		title: vehText
	});
	
	// Keep track of it
	vehicleMarkers[routeid][location[3]] = marker;
}

//update bus markers on a given route
function updateVehicleMarkers(routeid, markers)
{
	var latlng;
	var vehicleData = {}
	
	$.getJSON(rosseletURL + 'getvehicles.php?id=' + routeid, function(data) {
		// Build vehicle data dictionary from returned data
		// So we can check whether the vehicle is still on the road
		$.each(data.items, function(index, info) {
			vehicleData[info.id] = info
		})
		
		// For each marker, update position if exists, else delete marker
		$.each(markers, function(vehicleid, marker) {
			if (vehicleid in vehicleData) {
				latlng = new google.maps.LatLng(vehicleData[vehicleid].latitude, vehicleData[vehicleid].longitude);
				marker.setPosition(latlng)
				delete vehicleData[vehicleid]
			}
			
			// Vehicle disappeared
			else {
				deleteSingleVehicle(routeid, vehicleid)
			}
		})
		
		// leftover vehicle data are new buses that came on
		$.each(vehicleData, function(vehicleid, location) {
			info = [location.latitude, location.longitude, location.dir_name, location.id, location.run_id]
			drawVehicleMarker(routeid, info)
		})
	})	
	
}

// define a map marker for each position in the locations array			  
function addNearbyMarkers(locations) {
	var marker
	for (var i = 0; i < locations.length; i++) {
		// Add the marker with the hover text
		hoverText = makeNearbyHoverText(locations[i]);
		marker = new google.maps.Marker({
			position: new google.maps.LatLng(locations[i][1], locations[i][2]),
			map: map,
			title: hoverText,
			icon: "media/nearby_icon.gif"
		});
		
		// Add a clickable event with click text
		google.maps.event.addListener(marker, 'click', (function(marker, i) {
			return function() {
				makeNearbyClickText(locations[i], marker)
				
			}
		})(marker, i));
	}
}

//add nearby stops within 1km distance
function addNearbyStops() {
	
	var locations = []
	var marker; 
	$.getJSON(serviceURL + "php/nearme.php?lat=" + lat + "&lon=" + lon, function(data) {
        var stopList = data.items;  // extract the list of nearby stops
		$.each(stopList, function(index, stop) {
			locations.push([stop.display_name, stop.latitude, stop.longitude,
				stop.id, stop.routeid, stop.run_display_name,
				stop.distance*1000])  // convert mile distance to meters
				
		});
		addNearbyMarkers(locations)
		
    })
}

//add the current location marker
function addCurrentLocation(lat, lon) {
	
	var pinColor = "0000FF";
	var pinImage = new google.maps.MarkerImage("media/star_icon.png",
		new google.maps.Size(48, 48),
		new google.maps.Point(0,0),
		new google.maps.Point(10, 34)
	);
	
	marker = new google.maps.Marker({
		position: new google.maps.LatLng(lat, lon),
		map: map,
		icon: pinImage,
		title: "we're here"
	});
}		 

// refresh vehicles

function refreshVehicles()
{
	$.each(vehicleMarkers, function(routeid, markers) {		
		updateVehicleMarkers(routeid,markers)
	})
}

// Create the map
function createMap(lat, lon) {
	
	// initialize the map with zoom level, centre-geolocation, map type
	map = new google.maps.Map($('#gmap')[0], {
      zoom: 14,
      center: new google.maps.LatLng(lat, lon),
      mapTypeId: google.maps.MapTypeId.ROADMAP
    });
    
    // initialize dictionaries
    stopMarkers = {}
	vehicleMarkers = {}
}

// Draw our map for the first time
function drawMap(lat, lon) {
    
    addCurrentLocation(lat, lon)
    
    if (showNearby)
		addNearbyStops()
    
    // Add route stops
    $.each(mapRoutes, function(index, routeid) {
		addNewStopMarkers(routeid)
	})
    
    // Add route vehicles
    $.each(mapVehicles, function(index, routeid) {
		addNewVehicleMarkers(routeid)
	})
}

//add or delete stop marker for a specified route
$( '.sliderStops' ).live( 'slidestop', function( event ) {
	var elmts = $(this).closest("li").find("a.getDir");
	routeid = elmts[0].id
	if($(this).val() == "on"){
		$.mobile.changePage('#page_map')
		mapRoutes.push(routeid)
		addNewStopMarkers(routeid)		
	}
	else {
		if(mapRoutes.indexOf(routeid) != -1){
			mapRoutes.splice(mapRoutes.indexOf(routeid),1)
			deleteStopMarkers(routeid)
		}
	}
});

//add or delete vehicle marker for a specified route
$( '.sliderVehicles' ).live( 'slidestop', function( event ) {
	var elmts = $(this).closest("li").find("a.getDir");
	routeid = elmts[0].id
	if($(this).val() == "on"){
		$.mobile.changePage('#page_map')
		mapVehicles.push(routeid)
		addNewVehicleMarkers(routeid)
		
	}
	else {
		if(mapVehicles.indexOf(routeid) != -1){
			mapVehicles.splice(mapVehicles.indexOf(routeid),1)
			deleteVehicleMarkers(routeid)
		}
	}
});
